package cn.zuo.utils;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
/**
 * @Author 白白旧维
 * @Date 2021/7/7 11:13
 */
public class RSA {
    //签名，私钥签名
    public static List<BigInteger> signed_mul(BigInteger d,BigInteger n,String hm){//先H(m)，在签名
        return encryption_mul(d,n,hm);
    }


    //验证，公钥验证
    public static String verify_mul_hm(BigInteger e,BigInteger n,List<BigInteger> slist){//解密返回H(m)
        return decryption_mul(e,n,slist);
    }


    public static List<BigInteger> encryption_mul(BigInteger e, BigInteger n, String m){//加密，返回long数组

        List<BigInteger> clist = new ArrayList<>();
        for(int i=0;i<m.length();i++){
            BigInteger c = encryption_one(e,n,new BigInteger((int)m.charAt(i)+""));
            clist.add(c);
        }
        return clist;

    }

    public static String decryption_mul(BigInteger d,BigInteger n,List<BigInteger> clist){//解密,返回字符串

        char[] mm = new char[clist.size()];
        for(int i=0;i<clist.size();i++){
            mm[i] = (char) decryption_one(d,n,clist.get(i)).intValue();
        }
        return String.valueOf(mm);

    }


    private static BigInteger encryption_one(BigInteger e,BigInteger n,BigInteger m){//m^e%n

        return my_pow(m,e,n);//10000^65537 % 104 8583 0734 0081
    }

    private static BigInteger decryption_one(BigInteger d,BigInteger n,BigInteger c){//c^d%n

        return my_pow(c,d,n);

    }


    private static BigInteger my_pow(BigInteger x,BigInteger n,BigInteger m){//m^e%n,,c^d%n，二分快速幂
        BigInteger r = new BigInteger("1");//最终求余结果
        while(n.compareTo(new BigInteger("0"))==1){
            if(n.mod(new BigInteger("2")).compareTo(new BigInteger("1"))==0) {//只要最低位为1就可以更新结果
                r = r.multiply(x).mod(m);
            }
            n = n.divide(new BigInteger("2"));
            x = x.multiply(x).mod(m);
        }
        return r;
    }



}
